package config

import (
	"common_demo/pkg/utils/watchdog"
	"context"
	"fmt"
	"os"
	"sync"
	"syscall"

	"github.com/fsnotify/fsnotify"

	"gopkg.in/yaml.v3"
)

const DefaultConfig = "../internal/config/config.yaml"

var (
	once sync.Once

	Config   = new(config)
	SignalCh = make(chan os.Signal, 1)
)

type config struct {
	Logger   *LoggerConfig   `yaml:"logger"`
	Server   *ServerConfig   `yaml:"server"`
	Kuber    *KuberConfig    `yaml:"kubernetes"`
	Database *DatabaseConfig `yaml:"database"`
	Redis    *RedisConfig    `yaml:"redis"`
}

// logger 配置
type LoggerConfig struct {
	Level            string   `yaml:"level"`
	OutputPaths      []string `yaml:"output"`
	ErrorOutputPaths []string `yaml:"error_output"`
}

// server 配置
type ServerConfig struct {
	Name string `yaml:"name"`
	Host string `yaml:"host"`
}

// kubernetes 配置
type KuberConfig struct {
	Config string `yaml:"config"`
}

// database 配置
type DatabaseConfig struct {
	Path string `yaml:"path"`
}

// redis 配置
type RedisConfig struct {
	Address  string `yaml:"address"`
	Password string `yaml:"password"`
}

// 加载配置文件配置
func LoadConfiguration(ctx context.Context) error {
	file, err := os.ReadFile(DefaultConfig)
	if err != nil {
		return err
	}
	if err := yaml.Unmarshal(file, Config); err != nil {
		return err
	}

	once.Do(func() {
		if err = watchConfiguration(ctx); err != nil {
			panic(err)
		}
	})

	return nil
}

// 监控配置文件
func watchConfiguration(ctx context.Context) error {
	configWatcher, err := watchdog.NewWatchdog(ctx, "configWatcher")
	if err != nil {
		return err
	}
	configWatcher.Start()

	return configWatcher.AddPath(DefaultConfig, func(op fsnotify.Op) {
		if err := LoadConfiguration(ctx); err != nil {
			return
		}
		// 配置变更, 通知服务重新加载
		fmt.Println("Config changed, notify signal: SIGHUP")
		SignalCh <- syscall.SIGHUP
	})
}
